<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title id="pageTitle">接口文档</title>
  <link rel="icon" type="image/png" sizes="56x56" href="FreeAPI.png" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
  <link rel="stylesheet" href="css/style.css" />
  <style>
    /* 文档页面特定样式 */
    .doc-container {
      background-color: var(--card-bg);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      padding: 30px;
      margin-top: 20px;
      border: 1px solid var(--border-color);
    }
    
    .doc-header {
      display: flex;
      align-items: center;
      gap: 15px;
      margin-bottom: 25px;
      padding-bottom: 15px;
      border-bottom: 1px solid var(--border-color);
    }
    
    .doc-icon {
      width: 60px;
      height: 60px;
      background-color: var(--primary);
      color: white;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 24px;
    }
    
    .doc-title {
      margin: 0;
      color: var(--primary);
    }
    
    .doc-type {
      background-color: var(--deploy-info-bg);
      color: var(--primary);
      padding: 4px 10px;
      border-radius: 20px;
      font-size: 0.9rem;
      display: inline-block;
      margin-top: 5px;
    }
    
    .doc-calls {
      color: var(--gray);
      font-size: 0.9rem;
      margin-top: 5px;
    }
    
    .doc-section {
      margin-bottom: 30px;
    }
    
    .doc-section-title {
      font-size: 1.2rem;
      margin-bottom: 15px;
      color: var(--text-color);
      border-left: 4px solid var(--primary);
      padding-left: 10px;
    }
    
    .doc-table {
      width: 100%;
      border-collapse: collapse;
      margin-bottom: 20px;
    }
    
    .doc-table th, .doc-table td {
      padding: 12px 15px;
      text-align: left;
      border-bottom: 1px solid var(--border-color);
    }
    
    .doc-table th {
      background-color: var(--tip-box-bg);
      font-weight: 600;
    }
    
    .doc-code {
      background-color: var(--tip-box-bg);
      border-radius: var(--radius);
      padding: 15px;
      margin: 15px 0;
      overflow-x: auto;
      font-family: monospace;
      position: relative;
    }
    
    .doc-code-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
      font-size: 0.9rem;
      color: var(--gray);
    }
    
    .doc-code-copy {
      background: none;
      border: none;
      color: var(--primary);
      cursor: pointer;
      font-size: 0.9rem;
      display: flex;
      align-items: center;
      gap: 5px;
    }
    
    .doc-code pre {
      margin: 0;
      white-space: pre-wrap;
      word-break: break-word;
    }
    
    .doc-back {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      color: var(--primary);
      text-decoration: none;
      margin-bottom: 20px;
      font-weight: 500;
    }
    
    .doc-back:hover {
      text-decoration: underline;
    }
    
    .doc-loading {
      text-align: center;
      padding: 50px 0;
      color: var(--gray);
    }
    
    .doc-error {
      background-color: rgba(229, 62, 62, 0.1);
      border-left: 4px solid var(--error);
      padding: 15px;
      margin: 20px 0;
      color: var(--error);
    }
  </style>
</head>
<body>

<div data-include="nav.html"></div>

<!-- 页面主体内容 -->
<div class="container">
  <a href="/" class="doc-back">
    <i class="fas fa-arrow-left"></i> 返回首页
  </a>
  
  <div class="doc-container" id="docContainer">
    <div class="doc-loading" id="docLoading">
      <div class="loader-spinner"></div>
      <p>正在加载接口数据...</p>
    </div>
  </div>
  
  <div data-include="footer.html"></div>
</div>

<!-- 浮动按钮 -->
<div class="floating-buttons">
  <button id="theme-toggle" class="floating-btn" aria-label="切换主题">
    <i class="fas fa-moon"></i>
  </button>
  <button id="scroll-to-top" class="floating-btn" aria-label="返回顶部">
    <i class="fas fa-arrow-up"></i>
  </button>
</div>

<!-- 脚本 -->
<script src="js/main.js" defer></script>
<script src="js/toproll.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded', async function() {
  await loadIncludes();
  initializeTopNav();    // 确保调用了initializeTopNav函数
  loadDocData();         // 确保调用loadDocData函数
  
  // 添加主题切换功能
  const themeToggleBtn = document.getElementById('theme-toggle');
  const htmlElement = document.documentElement;
  const scrollToTopBtn = document.getElementById('scroll-to-top');
  
  // 应用主题
  const applyTheme = (theme) => {
    htmlElement.setAttribute('data-theme', theme);
    localStorage.setItem('theme', theme);
    const themeIcon = themeToggleBtn?.querySelector('i');
    if (themeIcon) {
      themeIcon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
    }
    themeToggleBtn?.setAttribute('aria-label', theme === 'dark' ? '切换到亮色主题' : '切换到暗色主题');
  };

  // 初始化主题
  const initTheme = () => {
    const savedTheme = localStorage.getItem('theme');
    const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    const currentTheme = savedTheme || (systemPrefersDark ? 'dark' : 'light');
    applyTheme(currentTheme);
  };

  // 点击主题按钮切换
  themeToggleBtn?.addEventListener('click', () => {
    const currentTheme = htmlElement.getAttribute('data-theme');
    const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
    applyTheme(newTheme);
    themeToggleBtn.style.transform = 'scale(0.8)';
    setTimeout(() => {
      themeToggleBtn.style.transform = '';
    }, 300);
  });

  // 初始化主题
  initTheme();
  
  // 返回顶部按钮
  window.addEventListener('scroll', () => {
    if (!scrollToTopBtn) return;
    if (window.pageYOffset > 200) {
      scrollToTopBtn.style.display = 'flex';
      scrollToTopBtn.style.opacity = '1';
    } else {
      scrollToTopBtn.style.opacity = '0';
      setTimeout(() => {
        if (window.pageYOffset <= 200) {
          scrollToTopBtn.style.display = 'none';
        }
      }, 300);
    }
  });

  scrollToTopBtn?.addEventListener('click', () => {
    scrollToTopBtn.style.transform = 'scale(0.8)';
    setTimeout(() => {
      scrollToTopBtn.style.transform = '';
    }, 300);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  });
});

// 检查文件是否存在
async function fileExists(url) {
  try {
    const response = await fetch(url, { method: 'HEAD' });
    return response.ok;
  } catch (error) {
    console.error('检查文件存在性失败:', error);
    return false;
  }
}

async function loadDocData() {
  const docContainer = document.getElementById('docContainer');
  const docLoading = document.getElementById('docLoading');
  
  try {
    // 从URL参数中获取ID
    const urlParams = new URLSearchParams(window.location.search);
    let docId = urlParams.get('id');
    
    // 如果没有URL参数，尝试从路径中获取
    if (!docId) {
      const pathParts = window.location.pathname.split('/');
      
      // 如果路径是 /doc/1 格式，提取ID
      if (pathParts.includes('doc')) {
        docId = pathParts[pathParts.indexOf('doc') + 1];
      } else {
        // 否则尝试获取最后一个路径部分
        docId = pathParts[pathParts.length - 1];
        // 如果最后一个部分是doc.html，则无效
        if (docId === 'doc.html') {
          docId = null;
        }
      }
    }
    
    // 如果没有ID或不是数字，显示错误
    if (!docId || isNaN(parseInt(docId))) {
      throw new Error('无效的接口ID');
    }
    
    // 先检查文件是否存在
    const jsonUrl = `data/${docId}.json`;
    const exists = await fileExists(jsonUrl);
    
    if (!exists) {
      throw new Error(`找不到接口 #${docId}，该接口可能不存在或已被移除`);
    }
    
    // 加载对应的JSON数据
    try {
      const response = await fetch(jsonUrl);
      
      // 检查响应类型是否为JSON
      const contentType = response.headers.get('content-type');
      if (!contentType || !contentType.includes('application/json')) {
        throw new Error(`找不到接口 #${docId}，该接口可能不存在或已被移除`);
      }
      
      if (!response.ok) {
        if (response.status === 404) {
          throw new Error(`找不到接口 #${docId}，该接口可能不存在或已被移除`);
        } else {
          throw new Error(`接口数据加载失败: ${response.status}`);
        }
      }
      
      let data;
      try {
        data = await response.json();
      } catch (jsonError) {
        console.error('JSON解析错误:', jsonError);
        throw new Error(`找不到接口 #${docId}，该接口可能不存在或已被移除`);
      }
      
      document.title = `${data.title || '接口文档'} - 接口文档`;
      
      // 渲染接口文档
      docContainer.innerHTML = `
        <div class="doc-header">
          <div class="doc-icon">
            <i class="fas fa-cloud"></i>
          </div>
          <div>
            <h1 class="doc-title">${data.title || '接口文档'}</h1>
          </div>
        </div>
        
        <div class="doc-section">
          <h2 class="doc-section-title">接口详情</h2>
          <p>${data.description || '暂无详细描述'}</p>
        </div>
        
        <div class="doc-section">
          <h2 class="doc-section-title">接口地址</h2>
          <div class="doc-code">
            <div class="doc-code-header">
              <span>URL</span>
              <button class="doc-code-copy" onclick="copyToClipboard('${data.url || ''}')">
                <i class="fas fa-copy"></i> 复制
              </button>
            </div>
            <pre>${data.url || '暂无接口地址'}</pre>
          </div>
        </div>
        
        <div class="doc-section">
          <h2 class="doc-section-title">请求方式</h2>
          <p>${data.method || 'GET/POST'}</p>
        </div>
        
        <div class="doc-section">
          <h2 class="doc-section-title">返回格式</h2>
          <p>${data.returnFormat || 'application/json'}</p>
        </div>
        
        ${renderParamsTable(data.params)}
        
        <div class="doc-section">
          <h2 class="doc-section-title">返回示例</h2>
          <div class="doc-code">
            <div class="doc-code-header">
              <span>实时结果</span>
              <button class="doc-code-copy" onclick="copyToClipboard(document.getElementById('apiResult').textContent)">
                <i class="fas fa-copy"></i> 复制
              </button>
            </div>
            <div id="apiResultLoading" style="text-align: center; padding: 20px;">
              <div class="loader-spinner"></div>
              <p>正在请求API数据...</p>
            </div>
            <div id="apiResult" class="json-tree" style="display: none;"></div>
          </div>
        </div>
        
        ${renderReturnParamsTable(data.returnParams)}
      `;
      
      // 立即请求API获取实时结果
      refreshApiResult(data.url);
      
    } catch (error) {
      console.error('文档加载失败:', error);
      docContainer.innerHTML = `
        <div class="doc-error">
          <h2><i class="fas fa-exclamation-triangle"></i> 加载失败</h2>
          <p>${error.message || '无法加载接口文档'}</p>
          <a href="/" class="doc-back">返回接口列表</a>
        </div>
      `;
    }
  } catch (error) {
    console.error('参数解析失败:', error);
    docContainer.innerHTML = `
      <div class="doc-error">
        <h2><i class="fas fa-exclamation-triangle"></i> 请求错误</h2>
        <p>${error.message || '无效的请求参数'}</p>
        <a href="/" class="doc-back">返回接口列表</a>
      </div>
    `;
  } finally {
    docLoading.style.display = 'none';
  }
}

// 渲染请求参数表格
function renderParamsTable(params) {
  if (!params || params.length === 0) {
    return `
      <div class="doc-section">
        <h2 class="doc-section-title">请求参数</h2>
        <p>无需请求参数</p>
      </div>
    `;
  }
  
  return `
    <div class="doc-section">
      <h2 class="doc-section-title">请求参数</h2>
      <table class="doc-table">
        <thead>
          <tr>
            <th>名称</th>
            <th>必填</th>
            <th>类型</th>
            <th>示例值</th>
            <th>说明</th>
          </tr>
        </thead>
        <tbody>
          ${params.map(param => `
            <tr>
              <td>${param.name || ''}</td>
              <td>${param.required ? '是' : '否'}</td>
              <td>${param.type || ''}</td>
              <td>${param.example || ''}</td>
              <td>${param.description || ''}</td>
            </tr>
          `).join('')}
        </tbody>
      </table>
    </div>
  `;
}

// 渲染返回参数表格
function renderReturnParamsTable(params) {
  if (!params || params.length === 0) {
    return `
      <div class="doc-section">
        <h2 class="doc-section-title">返回参数说明</h2>
        <p>无返回参数说明</p>
      </div>
    `;
  }
  
  return `
    <div class="doc-section">
      <h2 class="doc-section-title">返回参数说明</h2>
      <table class="doc-table">
        <thead>
          <tr>
            <th>名称</th>
            <th>类型</th>
            <th>说明</th>
          </tr>
        </thead>
        <tbody>
          ${params.map(param => `
            <tr>
              <td>${param.name || ''}</td>
              <td>${param.type || ''}</td>
              <td>${param.description || ''}</td>
            </tr>
          `).join('')}
        </tbody>
      </table>
    </div>
  `;
}

// 格式化JSON显示
function formatJSON(json) {
  try {
    return JSON.stringify(json, null, 2)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  } catch (e) {
    return '无效的JSON数据';
  }
}

// 复制到剪贴板
function copyToClipboard(text) {
  navigator.clipboard.writeText(text).then(() => {
    alert('已复制到剪贴板');
  }).catch(err => {
    console.error('复制失败:', err);
  });
}

// 刷新API结果
async function refreshApiResult(apiUrl) {
  if (!apiUrl) {
    document.getElementById('apiResultLoading').style.display = 'none';
    document.getElementById('apiResult').style.display = 'block';
    document.getElementById('apiResult').innerHTML = '<div class="json-error">无效的API地址</div>';
    return;
  }
  
  // 显示加载中提示
  document.getElementById('apiResultLoading').style.display = 'block';
  document.getElementById('apiResult').style.display = 'none';
  
  try {
    const response = await fetch(apiUrl);
    
    if (!response.ok) {
      throw new Error(`API请求失败: ${response.status}`);
    }
    
    let data;
    try {
      data = await response.json();
    } catch (jsonError) {
      console.error('API结果JSON解析错误:', jsonError);
      throw new Error('API返回的数据格式无效');
    }
    
    // 隐藏加载中提示
    document.getElementById('apiResultLoading').style.display = 'none';
    
    // 显示JSON树
    const apiResultElement = document.getElementById('apiResult');
    apiResultElement.style.display = 'block';
    
    // 渲染JSON树
    renderJsonTree(apiResultElement, data);
    
  } catch (error) {
    console.error('获取API结果失败:', error);
    document.getElementById('apiResultLoading').style.display = 'none';
    document.getElementById('apiResult').style.display = 'block';
    document.getElementById('apiResult').innerHTML = `<div class="json-error">${error.message || 'API请求失败'}</div>`;
  }
}

// 渲染可折叠的JSON树
function renderJsonTree(container, data) {
  container.innerHTML = '';
  const tree = document.createElement('div');
  tree.className = 'json-tree-root';
  container.appendChild(tree);
  
  // 添加CSS样式
  if (!document.getElementById('json-tree-style')) {
    const style = document.createElement('style');
    style.id = 'json-tree-style';
    style.textContent = `
      .json-tree-root {
        font-family: monospace;
        font-size: 14px;
        line-height: 1.5;
      }
      .json-tree-key {
        color: var(--primary);
        cursor: pointer;
      }
      .json-tree-value {
        color: var(--text-color);
      }
      .json-tree-string {
        color: #388E3C;
      }
      .json-tree-number {
        color: #0277BD;
      }
      .json-tree-boolean {
        color: #F57C00;
      }
      .json-tree-null {
        color: #9C27B0;
      }
      .json-tree-bracket {
        cursor: pointer;
      }
      .json-tree-collapsed > .json-tree-content {
        display: none;
      }
      .json-tree-expanded > .json-tree-content {
        display: block;
        padding-left: 20px;
      }
      .json-tree-toggle {
        display: inline-block;
        width: 12px;
        height: 12px;
        text-align: center;
        line-height: 12px;
        cursor: pointer;
        margin-right: 5px;
      }
    `;
    document.head.appendChild(style);
  }
  
  function createNode(key, value, isRoot = false) {
    const node = document.createElement('div');
    
    if (typeof value === 'object' && value !== null) {
      // 对象或数组
      const isArray = Array.isArray(value);
      const isEmpty = Object.keys(value).length === 0;
      
      if (!isRoot) {
        const toggle = document.createElement('span');
        toggle.className = 'json-tree-toggle';
        toggle.textContent = '▶';
        toggle.onclick = function() {
          const isCollapsed = node.classList.contains('json-tree-collapsed');
          node.classList.toggle('json-tree-collapsed', !isCollapsed);
          node.classList.toggle('json-tree-expanded', isCollapsed);
          toggle.textContent = isCollapsed ? '▼' : '▶';
        };
        node.appendChild(toggle);
        
        const keySpan = document.createElement('span');
        keySpan.className = 'json-tree-key';
        keySpan.textContent = key + ': ';
        keySpan.onclick = toggle.onclick;
        node.appendChild(keySpan);
      }
      
      const openBracket = document.createElement('span');
      openBracket.className = 'json-tree-bracket';
      openBracket.textContent = isArray ? '[' : '{';
      openBracket.onclick = function() {
        const isCollapsed = node.classList.contains('json-tree-collapsed');
        node.classList.toggle('json-tree-collapsed', !isCollapsed);
        node.classList.toggle('json-tree-expanded', isCollapsed);
        if (node.querySelector('.json-tree-toggle')) {
          node.querySelector('.json-tree-toggle').textContent = isCollapsed ? '▼' : '▶';
        }
      };
      node.appendChild(openBracket);
      
      if (isEmpty) {
        const closeBracket = document.createElement('span');
        closeBracket.className = 'json-tree-bracket';
        closeBracket.textContent = isArray ? ']' : '}';
        node.appendChild(closeBracket);
      } else {
        const content = document.createElement('div');
        content.className = 'json-tree-content';
        
        Object.keys(value).forEach((k, i, arr) => {
          const childNode = createNode(k, value[k]);
          if (i < arr.length - 1) {
            childNode.appendChild(document.createTextNode(','));
          }
          content.appendChild(childNode);
        });
        
        node.appendChild(content);
        
        const closeBracket = document.createElement('span');
        closeBracket.className = 'json-tree-bracket';
        closeBracket.textContent = isArray ? ']' : '}';
        node.appendChild(closeBracket);
        
        // 默认展开根节点，折叠其他节点
        if (isRoot) {
          node.classList.add('json-tree-expanded');
        } else {
          node.classList.add('json-tree-collapsed');
        }
      }
    } else {
      // 基本类型值
      if (!isRoot) {
        const keySpan = document.createElement('span');
        keySpan.className = 'json-tree-key';
        keySpan.textContent = key + ': ';
        node.appendChild(keySpan);
      }
      
      const valueSpan = document.createElement('span');
      valueSpan.className = 'json-tree-value';
      
      if (typeof value === 'string') {
        valueSpan.className += ' json-tree-string';
        valueSpan.textContent = `"${value}"`;
      } else if (typeof value === 'number') {
        valueSpan.className += ' json-tree-number';
        valueSpan.textContent = value;
      } else if (typeof value === 'boolean') {
        valueSpan.className += ' json-tree-boolean';
        valueSpan.textContent = value;
      } else {
        valueSpan.className += ' json-tree-null';
        valueSpan.textContent = 'null';
      }
      
      node.appendChild(valueSpan);
    }
    
    return node;
  }
  
  tree.appendChild(createNode('root', data, true));
}
</script>
</body>
</html> 
